package com.quanyan.authority.service.impl;

import com.lefu.commons.utils.Page;
import com.quanyan.authority.cache.AuthorityRedisTemplate;
import com.quanyan.authority.constants.AuthorityConstants;
import com.quanyan.authority.mapper.RoleMenuMapper;
import com.quanyan.authority.mapper.TbAdminUserRoleMapper;
import com.quanyan.authority.mapper.TbMenuMapper;
import com.quanyan.authority.mapper.TbRoleMapper;
import com.quanyan.authority.model.db.*;
import com.quanyan.authority.model.request.ReqMenu;
import com.quanyan.authority.model.request.ReqPage;
import com.quanyan.authority.model.response.RespLogin;
import com.quanyan.authority.model.response.RespMenu;
import com.quanyan.authority.service.MenuService;
import com.quanyan.common.constants.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.List;

/**
 * Created by Administrator on 2016/8/1.
 */
@Service
public class MenuServiceImpl implements MenuService{

    private static final Logger logger = LoggerFactory.getLogger(MenuServiceImpl.class);

    @Autowired
    private TbMenuMapper tbMenuMapper;

    @Autowired
    private AuthorityRedisTemplate authorityRedisTemplate;

    @Autowired
    private RoleMenuMapper roleMenuMapper;



    @Override
    public TbMenu findById(Integer id) {
        if(id == null)
            return null;
        return tbMenuMapper.selectByPrimaryKey(id);
    }

    @Override
    public TbMenu add(ReqMenu reqBaseParam) {
        TbMenu tbMenu = new TbMenu();
        tbMenu.setName(reqBaseParam.getName());
        tbMenu.setRemark(reqBaseParam.getRemark());
        tbMenu.setIsDelete(reqBaseParam.getIsDelete().byteValue());
        tbMenu.setIcon(reqBaseParam.getIcon());
        tbMenu.setParentId(reqBaseParam.getParentId());
        tbMenu.setSort(reqBaseParam.getSort());
        tbMenu.setUrl(reqBaseParam.getUrl());
        tbMenu.setCreateTime(new Date());
        tbMenu.setUpdateTime(new Date());
        tbMenu.setFounder(reqBaseParam.getFounder());
        tbMenu.setFounderName(reqBaseParam.getFounderName());
        tbMenu.setType(reqBaseParam.getResourcesType().byteValue());
        tbMenu.setCode(reqBaseParam.getCode());
        TbMenu tbMenu1 = this.findById(tbMenu.getId());
        if(tbMenu1!=null){
            if(tbMenu1.getLevle() != null){
                Integer i = tbMenu1.getLevle().intValue()+1;
                tbMenu.setLevle(i.byteValue());
            }
        }
        tbMenuMapper.insertSelective(tbMenu);
        //authorityRedisTemplate.hset(AuthorityConstants.MENU_REDIS_KEY,tbMenu.getId().toString(),tbMenu);
        return tbMenu;
    }

    @Override
    public void del(Integer id) {
        if(id!=null){
            tbMenuMapper.deleteByPrimaryKey(id);
            //authorityRedisTemplate.hdel(AuthorityConstants.MENU_REDIS_KEY,id.toString());
        }

    }

    @Override
    public void update(ReqMenu reqBaseParam) {
        TbMenu tbMenu = new TbMenu();
        tbMenu.setId(reqBaseParam.getId());
        tbMenu.setName(reqBaseParam.getName());
        tbMenu.setRemark(reqBaseParam.getRemark());
        tbMenu.setIsDelete(reqBaseParam.getIsDelete().byteValue());
        tbMenu.setIcon(reqBaseParam.getIcon());
        tbMenu.setSort(reqBaseParam.getSort());
        tbMenu.setUrl(reqBaseParam.getUrl());
        tbMenu.setUpdateTime(new Date());
        tbMenuMapper.updateByPrimaryKeySelective(tbMenu);
        //authorityRedisTemplate.hset(AuthorityConstants.MENU_REDIS_KEY,tbMenu.getId().toString(),tbMenuMapper.selectByPrimaryKey(tbMenu.getId()));

    }




    @Override
    public Page findAll(ReqPage reqPage, ReqMenu reqBaseParam) {
       return null;
    }

    @Override
    public void initMenu(){
        TbMenuExample example = new TbMenuExample();
        TbMenuExample.Criteria criteria = example.createCriteria();
        //criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        List<TbMenu> list =  tbMenuMapper.selectByExample(example);
        for (TbMenu tbMenu:list){
            authorityRedisTemplate.hset(AuthorityConstants.MENU_REDIS_KEY,tbMenu.getId().toString(),tbMenu);
        }
    }


    @Override
    public Map<String,Object> getUserMenu(Integer uid){
        List<RespMenu>  userMenus = new ArrayList<RespMenu>();// 用户拥有的菜单
        List<TbAdminUserRole> roleIdList = (List<TbAdminUserRole>)authorityRedisTemplate.get(AuthorityConstants.getUserRoleRedisKey(uid)); //用户拥有的角色
        List<TbRoleMenu> tbRoleMenus =(List<TbRoleMenu>) authorityRedisTemplate.get(AuthorityConstants.ROLE_MENU_REDIS_KEY);//角色拥有的菜单
        Map<Integer,TbMenu> mapMenu =(Map) authorityRedisTemplate.hget(AuthorityConstants.MENU_REDIS_KEY);//系统菜单

        Map<String,Object> m = new HashMap<String,Object>();
        List<TbMenu> lstFunction = new ArrayList<TbMenu>();
        boolean flag = this.isAdmin(roleIdList);
        if(flag){ // 如果是管理员  返回全部菜单
            for (Map.Entry<Integer,TbMenu> entry:mapMenu.entrySet()){
                 TbMenu tbMenu = entry.getValue();
                 userMenus.add(this.covertToRespUserMenu(tbMenu));
                 lstFunction.add(tbMenu);
            }
            m.put("respUserMenu",this.getMenuTree(userMenus));
            m.put("respUserFunction",lstFunction);
            return m;
        }

        Set<Integer> set = new HashSet<Integer>(); // menuId
        for (TbAdminUserRole r : roleIdList) {
            for (TbRoleMenu rm : tbRoleMenus) {
                if ( r.getRoleId().intValue() == rm.getRoleId().intValue())
                    set.add(rm.getMenuId());
            }
        }

        for (Integer mid:set){
            if (mapMenu.containsKey(mid.toString())){
                TbMenu t = mapMenu.get(mid.toString());
                userMenus.add(this.covertToRespUserMenu(t));
                lstFunction.add(t);
            }
        }
        m.put("respUserMenu",this.getMenuTree(userMenus));
        m.put("respUserFunction",lstFunction);
        return m;
    }


    public RespLogin getUserMenuNew(Integer uid){
        RespLogin respLogin = new RespLogin();
        TbAdminUserRoleExample example = new TbAdminUserRoleExample();
        TbAdminUserRoleExample.Criteria criteria = example.createCriteria();
        criteria.andUidEqualTo(uid);
        List<TbAdminUserRole> lstUr= (List<TbAdminUserRole>)authorityRedisTemplate.get(AuthorityConstants.getUserRoleRedisKey(uid)); // 用户拥有角色
        logger.info("用户：{}，拥有的角色{}",uid,lstUr.toString());
        if(isMaster(lstUr)){
            logger.info("为管理员用户");
            List<TbMenu> lstTbMenu =  tbMenuMapper.selectByExample(new TbMenuExample());
            List<RespMenu> userMenus = new ArrayList<>();
            for(TbMenu tbMenu :lstTbMenu){
                userMenus.add(this.covertToRespUserMenu(tbMenu));
            }
            respLogin.setRespUserFunction(lstTbMenu);
            respLogin.setRespUserMenu(this.getMenuTree(userMenus));
            return respLogin;
        }
        List<TbMenu> lst = roleMenuMapper.findMenuByUid(uid);
        List<RespMenu> treeList = new ArrayList<>();
        for (TbMenu t :lst){
            treeList.add(this.covertToRespUserMenu(t));
        }
        respLogin.setRespUserFunction(lst);
        respLogin.setRespUserMenu(this.getMenuTree(treeList));
        return respLogin;
    }

    public boolean isMaster(List<TbAdminUserRole> lstUr){
        if(lstUr == null && lstUr.size() < 1 )
            return false;

        for (TbAdminUserRole ur :lstUr){
            TbRole role =(TbRole)authorityRedisTemplate.hget(AuthorityConstants.ROLE_MAP_KEY,ur.getRoleId().toString());
            if(role.getCode().equals(AuthorityConstants.ROLE_CODE_ADMIN))
                return true;
        }
        return false;
    }

    /**
     * 转tree
     * @param menuList
     * @return
     */
    public List<RespMenu> getMenuTree(List<RespMenu> menuList){
        List<RespMenu> nodeList = new ArrayList<RespMenu>();
        for(RespMenu node1 : menuList){
            boolean mark = false;
            for(RespMenu node2 : menuList){
                if(node1.getParentId().equals(node2.getId())){
                    mark = true;
                    if(node2.getChildren() == null)
                        node2.setChildren(new ArrayList<RespMenu>());
                    node2.getChildren().add(node1);
                    break;
                }
            }
            if(!mark){
                nodeList.add(node1);
            }
        }
        Comparator<RespMenu> comparator = new Comparator<RespMenu>() {
            @Override
            public int compare(RespMenu o1, RespMenu o2) {
                return o1.getSort().compareTo(o2.getSort());
            }
        };
        Collections.sort(nodeList, comparator);
        return nodeList;
    }



    /**
     *
     * @param t
     * @return
     */
    public RespMenu covertToRespUserMenu(TbMenu t){
        RespMenu respMenu = new RespMenu();
        respMenu.setIcon(t.getIcon());
        respMenu.setId(t.getId());
        respMenu.setParentId(t.getParentId());
        respMenu.setName(t.getName());
        respMenu.setSort(t.getSort());
        respMenu.setUrl(t.getUrl());
        respMenu.setType(t.getType());
        respMenu.setIsDelete(t.getIsDelete());
        return respMenu;
    }

    /**
     * 判断是否拥有管理员角色
     */
    public boolean isAdmin(List<TbAdminUserRole> lstUR){
        Map<byte[], byte[]>  map = authorityRedisTemplate.hgetAll(AuthorityConstants.ROLE_MAP_KEY);
        for (TbAdminUserRole ur :lstUR){
            TbRole role =(TbRole)authorityRedisTemplate.hget(AuthorityConstants.ROLE_MAP_KEY,ur.getRoleId().toString());
            if(role.getCode().equals(AuthorityConstants.ROLE_CODE_ADMIN))
                return true;
        }
        return false;
    }

    public List<TbMenu> getMenuOne(){
        TbMenuExample example = new TbMenuExample();
        TbMenuExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        criteria.andParentIdEqualTo(1);
        criteria.andTypeEqualTo(AuthorityConstants.ResourcesType.menu);
        List<TbMenu> lst = tbMenuMapper.selectByExample(example);
        return lst;
    }

}
